#include "Resolver.h"
#include "Request.h"
#include "Logger.h"
#include "Config.h"

#include <fstream>
#include <vector>
#include <string>
#include <map>
using namespace std;


//TODO Sameer 
Resolver::Resolver( Logger& logg, Logger& Err , std::string c_Res ):LOGGER( logg ), ERRLOGGER(Err)
{
	m_strResFile = c_Res;
	currentIndex = c_startingIndex;
};

void Resolver::PrintResolver()
{
	LOGGER<<"\nEntering PrintResolver\n";
	std::map< std::string, int >::iterator it ;

	LOGGER<<"Resolver::PrintResolver"<< "Map size:"<<m_ResolveMap.size()<<"\n";

	for( it = m_ResolveMap.begin() ; it != m_ResolveMap.end(); it++  )
	{
		LOGGER<<"Resolver::PrintResolver "<<"m_ResolveMap[ "<<  it->first <<" ]:	"<< it->second<<"\n";
	}

	LOGGER<<"Resolver::PrintResolver "<<"Leaving PrintResolver\n\n";

}

bool Resolver::ParseResolveFile()
{
	//Parses system files already created in the system directory
	//Represents files that can be accessed by all clients.

	std::ifstream ReqFile;
	LOGGER<<"Resolver::ParseResolveFile "<<"m_strResFile: "<<m_strResFile<<"\n";
	ReqFile.open( m_strResFile.c_str() );

	if( !ReqFile )
	{
		ERRLOGGER<<"Resolver::PrintResolver "<<" File is not open, Check file name."<<"\n";
		return false;
	}

	std::string Line ;
	std::string strURL	= "NONE";
	int ID				= -1;

	while(  ReqFile.good() )
	{
		getline( ReqFile, Line );

		if( Line.length() == 0 )
			continue;

		//Remove comments
		if( Line.find('#') !=  std::string::npos )
		{
			Line.erase( Line.find_first_of('#') );
			if( Line.length() == 0 )
				continue;
		}
		strURL			=	Line.substr( 0, Line.find_first_of( '\t' ));
		std::string ss	=	Line.substr( Line.find_first_of( '\t' ) + 1 , Line.length() - 1 );
		ID				=	Convert::string_to_T<int>( ss );

		std::string strFileName = strURL;

		std::size_t	Idx	= strURL.find_last_of( "/" );
		if( Idx != std::string::npos )
		{
			strFileName = strURL.substr( Idx + 1, strURL.length()  - Idx );
		}

		//m_ResolveMap[ strURL ] = ID;
		m_ResolveMap.insert( std::pair< std::string, int >( strFileName, ID )  );

	}

	return true;
};

bool Resolver::Enque( Request* pReq )
{
	m_queue.push( pReq );
	//LOGGER<<"Resolver::Enque"<<"Queue Size: "<<m_queue.size()<<"\n";
	return true;
};


//Returns a pointer to request to process
//Returns NULL pointer in case the Queue is Empty.
Request* Resolver::GetReq( )
{

	Request* pReq = NULL;
	if( m_queue.size() > 0 )
	{
		pReq =	m_queue.front();
		m_queue.pop();
	}
	return pReq;
};



bool Resolver::Resolve( Request* c_pReq )
{
	using namespace std;

	//PrintResolver();
	LOGGER<<"Resolver::Resolve: resolving "<<c_pReq->m_strURL<<"\n";

	bool Resolved = false;
	typedef std::multimap< string, int  >::iterator __string__int__iterator;
	std::pair< __string__int__iterator ,  __string__int__iterator > ret;

	ret = m_ResolveMap.equal_range(c_pReq->m_strFileName );
	__string__int__iterator it;


	for( it = ret.first ; it != ret.second; it++ )
	{
			Resolved = true;
			LOGGER<<"Resolver::Resolve "<<"adding ID: "<<it->second<<"To the list \n";
			c_pReq->m_FileIDs.push_back( it->second );
	}

	c_pReq->m_bResolved = Resolved;

	return Resolved;
};


void Resolver::AddEntry( Request* pReq )
{
	currentIndex += 1 ;
	LOGGER<<"Resolver::AddEntry "<<pReq->m_strFileName <<"  "<< currentIndex<<"\n";
	m_ResolveMap.insert( std::pair< std::string, int >( pReq->m_strFileName , currentIndex ) );
	pReq->m_NewID	= currentIndex;
};

bool Resolver::CreateSystemFiles()
{
	//Creates all the system defined files.
	std::multimap< std::string, int >::iterator it ;
	for( it = m_ResolveMap.begin() ; it != m_ResolveMap.end(); it++  )
	{

	}
	return true;
}
